package com.mark.mall.web.platform.aop;

import com.mark.mall.common.myException.MyException;
import com.mark.mall.common.resultBean.R;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author licn
 * Created on 2021/1/7 14:29
 */
@Component
@Aspect
@Slf4j
public class AopConfig {
    /**
     * 反参为R的接口全部走aop处理，具体到反参添加public末尾无需<.>直接 *(..)即可，没有具体开头添加 * 结尾增加.*(..)
     */
    @Pointcut("execution( * com.mark.mall.web.platform.controller.*Controller.*(..))")
    public void aopConfig() {
    }

    @Around("aopConfig()")
    public R<?> around(ProceedingJoinPoint pjp) {
        R<?> result;
        try {
            long startTime = System.currentTimeMillis();
            Object[] args = pjp.getArgs();
            log.info("入参：" + Arrays.toString(args));
            result = (R<?>) pjp.proceed();
            long runTime = System.currentTimeMillis() - startTime;
            log.info("出参：" + result.getData());
            log.info("方法执行了{}ms", runTime);
        } catch (Throwable e) {
            result = handlerException(pjp, e);
        }
        return result;
    }

    /**
     * 封装异常信息，注意区分已知异常（自己抛出的）和未知异常，封装成R形式反参，为前端展示错误信息提供基础
     */
    private R<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
        R<?> result = new R<>();
        result.setCode(R.FAIL);
        if (e instanceof MyException) {
            // 已知异常特殊处理
            String msg = e.getLocalizedMessage();
            result.setMsg(msg);
            log.error("已知异常：" + msg);
        } else {
            result.setMsg("服务器异常，操作失败！");
            log.error(pjp.getSignature() + " error ", e);
        }
        return result;
    }
}
